namespace PugLib.UI
{
	using System;
	using System.Drawing;
	using System.Drawing.Drawing2D;
	using System.Drawing.Text;
	using System.Windows.Forms;

	internal partial class EmulateCommandLink : Button
	{
		private const int ARROW_WIDTH = 19;
		private const int LEFT_MARGIN = 10;
		private const int TOP_MARGIN = 10;
		private Image _arrowHovered;
		private Image _arrowNormal;
		private ButtonState _buttonState = ButtonState.Normal;

		internal EmulateCommandLink()
		{
			InitializeComponent();
			base.Font = new Font("Arial", 11.75F, FontStyle.Regular, GraphicsUnit.Point, 0);
			SmallFont = new Font("Arial", 8F, FontStyle.Regular, GraphicsUnit.Point, 0);
		}

		// Make sure the control is invalidated(repainted) when the text is changed.
		public override string Text
		{
			get { return base.Text; }
			set
			{
				base.Text = value;
				Invalidate();
			}
		}

		internal Font SmallFont { get; set; }

		internal int BestHeight
		{
			get { return (TOP_MARGIN * 2) + (int)(GetSmallTextSizeF().Height + GetLargeTextSizeF().Height); }
		}


		protected override void OnCreateControl()
		{
			base.OnCreateControl();
			_arrowNormal = TaskDialogImages.ArrowNormal;
			_arrowHovered = TaskDialogImages.ArrowHovered;
		}


		private string GetLargeText()
		{
			string[] lines = Text.Split(new[] { '\n' });
			return lines[0];
		}

		private string GetSmallText()
		{
			if (Text.IndexOf('\n') < 0)
			{
				return string.Empty;
			}

			string s = Text;
			string[] lines = s.Split(new[] { '\n' });
			s = string.Empty;
			for (int i = 1; i < lines.Length; i++)
			{
				s += lines[i] + "\n";
			}
			return s.Trim(new[] { '\n' });
		}

		private SizeF GetLargeTextSizeF()
		{
			const int x = LEFT_MARGIN + ARROW_WIDTH + 5;
			SizeF mzSize = new SizeF(Width - x - LEFT_MARGIN, 5000.0F); // presume RIGHT_MARGIN = LEFT_MARGIN
			Graphics g = Graphics.FromHwnd(Handle);
			SizeF textSize = g.MeasureString(GetLargeText(), base.Font, mzSize);
			return textSize;
		}

		private SizeF GetSmallTextSizeF()
		{
			string s = GetSmallText();
			if (string.IsNullOrEmpty(s))
			{
				return new SizeF(0, 0);
			}
			const int x = LEFT_MARGIN + ARROW_WIDTH + 8;
			SizeF mzSize = new SizeF(Width - x - LEFT_MARGIN, 5000.0F); // presume RIGHT_MARGIN = LEFT_MARGIN
			Graphics g = Graphics.FromHwnd(Handle);
			SizeF textSize = g.MeasureString(s, SmallFont, mzSize);
			return textSize;
		}


		protected override void OnPaint(PaintEventArgs e)
		{
			e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
			e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

			LinearGradientBrush brush;
			const LinearGradientMode mode = LinearGradientMode.Vertical;

			Rectangle newRect = new Rectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
			Color text_color = SystemColors.WindowText;

			Image img = _arrowNormal;

			if (Enabled)
			{
				switch (_buttonState)
				{
					case ButtonState.Normal:
						e.Graphics.FillRectangle(Brushes.White, newRect);
						if (base.Focused)
						{
							e.Graphics.DrawRectangle(new Pen(Color.SkyBlue, 1), newRect);
						}
						else
						{
							e.Graphics.DrawRectangle(new Pen(Color.White, 1), newRect);
						}
						text_color = Color.DarkBlue;
						break;

					case ButtonState.MouseOver:
						brush = new LinearGradientBrush(newRect, Color.White, Color.WhiteSmoke, mode);
						e.Graphics.FillRectangle(brush, newRect);
						e.Graphics.DrawRectangle(new Pen(Color.Silver, 1), newRect);
						img = _arrowHovered;
						text_color = Color.Blue;
						break;

					case ButtonState.Down:
						brush = new LinearGradientBrush(newRect, Color.WhiteSmoke, Color.White, mode);
						e.Graphics.FillRectangle(brush, newRect);
						e.Graphics.DrawRectangle(new Pen(Color.DarkGray, 1), newRect);
						text_color = Color.DarkBlue;
						break;
				}
			}
			else
			{
				brush = new LinearGradientBrush(newRect, Color.WhiteSmoke, Color.Gainsboro, mode);
				e.Graphics.FillRectangle(brush, newRect);
				e.Graphics.DrawRectangle(new Pen(Color.DarkGray, 1), newRect);
				text_color = Color.DarkBlue;
			}

			string largetext = GetLargeText();
			string smalltext = GetSmallText();

			SizeF szL = GetLargeTextSizeF();
			e.Graphics.DrawString(largetext, base.Font, new SolidBrush(text_color),
			                      new RectangleF(new PointF(LEFT_MARGIN + _arrowNormal.Width + 5, TOP_MARGIN), szL));

			if (!string.IsNullOrEmpty(smalltext))
			{
				SizeF szS = GetSmallTextSizeF();
				e.Graphics.DrawString(smalltext, SmallFont, new SolidBrush(text_color),
				                      new RectangleF(new PointF(LEFT_MARGIN + _arrowNormal.Width + 8, TOP_MARGIN + (int)szL.Height), szS));
			}

			e.Graphics.DrawImage(img, new Point(LEFT_MARGIN, TOP_MARGIN + (int)(szL.Height / 2) - (img.Height / 2)));
		}

		protected override void OnMouseLeave(EventArgs e)
		{
			_buttonState = ButtonState.Normal;
			Invalidate();
			base.OnMouseLeave(e);
		}

		protected override void OnMouseEnter(EventArgs e)
		{
			_buttonState = ButtonState.MouseOver;
			Invalidate();
			base.OnMouseEnter(e);
		}

		protected override void OnMouseUp(MouseEventArgs e)
		{
			_buttonState = ButtonState.MouseOver;
			Invalidate();
			base.OnMouseUp(e);
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			_buttonState = ButtonState.Down;
			Invalidate();
			base.OnMouseDown(e);
		}

		protected override void OnSizeChanged(EventArgs e)
		{
			int h = BestHeight;
			if (Height != h)
			{
				Height = h;
				return;
			}
			base.OnSizeChanged(e);
		}

		#region Nested type: ButtonState

		private enum ButtonState
		{
			Normal,
			MouseOver,
			Down
		}

		#endregion
	}
}